/**
 * API客户端工具
 * 支持重试、超时、429错误处理
 */

interface FetchOptions extends RequestInit {
  timeout?: number;
  retries?: number;
}

/**
 * 延迟函数
 */
function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

/**
 * 带超时的fetch
 */
async function fetchWithTimeout(
  url: string,
  options: FetchOptions = {}
): Promise<Response> {
  const { timeout = 10000, ...fetchOptions } = options;

  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, {
      ...fetchOptions,
      signal: controller.signal,
    });
    clearTimeout(timeoutId);
    return response;
  } catch (error) {
    clearTimeout(timeoutId);
    throw error;
  }
}

/**
 * 带重试和429处理的fetch
 */
export async function fetchWithRetry(
  url: string,
  options: FetchOptions = {}
): Promise<Response> {
  const { retries = 3, ...fetchOptions } = options;

  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetchWithTimeout(url, fetchOptions);

      // 429 错误处理
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
        
        console.warn(
          `Rate limited (429), retrying after ${waitTime / 1000}s... (attempt ${i + 1}/${retries})`
        );
        
        if (i < retries - 1) {
          await sleep(waitTime);
          continue;
        }
      }

      // 如果响应成功或是客户端错误（非429），直接返回
      if (response.ok || (response.status >= 400 && response.status < 500 && response.status !== 429)) {
        return response;
      }

      // 服务器错误（5xx），重试
      if (response.status >= 500 && i < retries - 1) {
        console.warn(
          `Server error (${response.status}), retrying... (attempt ${i + 1}/${retries})`
        );
        await sleep(Math.pow(2, i) * 1000); // 指数退避
        continue;
      }

      return response;
    } catch (error) {
      // 网络错误或超时
      if (i === retries - 1) {
        throw error;
      }

      console.warn(
        `Network error, retrying... (attempt ${i + 1}/${retries})`,
        error
      );
      await sleep(Math.pow(2, i) * 1000); // 指数退避
    }
  }

  throw new Error('Max retries exceeded');
}

/**
 * API请求包装器
 */
export async function apiRequest<T>(
  url: string,
  options: FetchOptions = {}
): Promise<T> {
  const response = await fetchWithRetry(url, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  if (!response.ok) {
    const error = await response.json().catch(() => ({
      message: `HTTP ${response.status}: ${response.statusText}`,
    }));
    throw new Error(error.message || 'API request failed');
  }

  return response.json();
}

/**
 * GET请求
 */
export function get<T>(url: string, options?: FetchOptions): Promise<T> {
  return apiRequest<T>(url, { ...options, method: 'GET' });
}

/**
 * POST请求
 */
export function post<T>(
  url: string,
  data?: any,
  options?: FetchOptions
): Promise<T> {
  return apiRequest<T>(url, {
    ...options,
    method: 'POST',
    body: JSON.stringify(data),
  });
}

